﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;

using WP7Contrib.View.Controls.Extensions;

namespace WP7Contrib.View.Controls.JumpList
{
  /// <summary>
  /// A list control for presenting long lists of data
  /// </summary>
  public partial class JumpList : Control, INotifyPropertyChanged
  {
    #region fields

    private bool _manipulationDeltaStarted = false;

    private ItemsControl _categoryItemsControl;

    private ItemsControl _jumpListControl;

    private FrameworkElement _loadingIndicator;

    private VirtualizingStackPanel _stackPanel;

    private ScrollViewer _scrollviewer;

    private List<object> _categoryList;

    private DoubleAnimation _scrollAnimation;

    private Storyboard _scrollStoryboard;

    private List<object> _flattenedCategories;

    #endregion

    #region VerticalOffset DP

    /// <summary>
    /// VerticalOffset, a private DP used to animate the scrollviewer
    /// </summary>
    private DependencyProperty VerticalOffsetProperty = DependencyProperty.Register("VerticalOffset",
      typeof(double), typeof(JumpList), new PropertyMetadata(0.0, OnVerticalOffsetChanged));

    private static void OnVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
      JumpList jumpList = d as JumpList;
      jumpList.OnVerticalOffsetChanged(e);
    }

    private void OnVerticalOffsetChanged(DependencyPropertyChangedEventArgs e)
    {
      SetVerticalOffset((double)e.NewValue);
    }

    #endregion

    #region DP change handlers

    partial void OnJumpListItemStylePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      RebuildCategorisedList();
    }

    partial void OnScrollDurationPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      // no-op
    }

    partial void OnIsCategoryViewShownPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      if ((bool)e.NewValue == true)
      {
        // first time load!
        if (_categoryItemsControl.Visibility == Visibility.Collapsed)
        {
          _loadingIndicator.Opacity = 1;
          _jumpListControl.Hide();

          Dispatcher.BeginInvoke(() =>
          {
            _categoryItemsControl.LayoutUpdated += new EventHandler(CategoryItemsControl_LayoutUpdated);
            _categoryItemsControl.Visibility = Visibility.Visible;
          });
        }
        else
        {
          _jumpListControl.Hide();
          _jumpListControl.IsHitTestVisible = false;
          _categoryItemsControl.IsHitTestVisible = true;
          ShowChildElements(_categoryItemsControl, TimeSpan.FromMilliseconds(CategoryTileAnimationDelay));
        }
      }
      else
      {
        _jumpListControl.Show();
        _jumpListControl.IsHitTestVisible = true;
        _categoryItemsControl.IsHitTestVisible = false;
        HideChildElements(_categoryItemsControl, TimeSpan.FromMilliseconds(CategoryTileAnimationDelay));
      }
    }

    partial void OnCategoryButtonTemplatePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      RebuildCategorisedList();
    }

    partial void OnCategoryButtonStylePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      RebuildCategorisedList();
    }

    partial void OnCategoryProviderPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      RebuildCategorisedList();
    }

    partial void OnCategoryButtonItemTemplatePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      RebuildCategorisedList();
    }

    partial void OnCategoryTileAnimationDelayPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      // no op
    }

    partial void OnItemTemplatePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      RebuildCategorisedList();
    }

    partial void OnJumpButtonStylePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      RebuildCategorisedList();
    }

    partial void OnJumpButtonTemplatePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      RebuildCategorisedList();
    }

    partial void OnItemsSourcePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      INotifyCollectionChanged oldIncc = e.OldValue as INotifyCollectionChanged;
      if (oldIncc != null)
      {
        oldIncc.CollectionChanged -= ItemsSource_CollectionChanged;
      }

      INotifyCollectionChanged incc = e.NewValue as INotifyCollectionChanged;
      if (incc != null)
      {
        incc.CollectionChanged += ItemsSource_CollectionChanged;
      }

      RebuildCategorisedList();
    }

    partial void OnSelectedItemPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
      var previousSelection = e.OldValue;

      // de-select the previous item
      var oldSelectedJumpListItem = FlattenedCategories.OfType<JumpListItem>()
                                                       .Where(i => i.Tag.Equals(previousSelection))
                                                       .SingleOrDefault();
      if (oldSelectedJumpListItem != null)
      {
        VisualStateManager.GoToState(oldSelectedJumpListItem, "Unselected", true);
      }

      // select the new item
      var newSelectedItem = FlattenedCategories.OfType<JumpListItem>()
                                                       .Where(i => i.Tag.Equals(SelectedItem))
                                                       .SingleOrDefault();
      if (newSelectedItem != null)
      {
        VisualStateManager.GoToState(newSelectedItem, "Selected", true);
      }

      // raise the selection changed event
      OnSelectionChanged(new SelectionChangedEventArgs(ToList(e.OldValue), ToList(e.NewValue)));
    }

    private IList ToList(object item)
    {
      IList asList = new List<object>();
      if (item != null)
        asList.Add(item);
      return asList;
    }


    #endregion

    #region properties

    /// <summary>
    /// Gets the categorised list of items
    /// </summary>
    public List<object> FlattenedCategories
    {
      get
      {
        return _flattenedCategories;
      }
      private set
      {
        _flattenedCategories = value;
        OnPropertyChanged("FlattenedCategories");
      }
    }

    /// <summary>
    /// Gets the virtualizing stack panel that hosts our jump list items
    /// </summary>
    private VirtualizingStackPanel ItemsHostStackPanel
    {
      get
      {
        if (_stackPanel == null)
        {
          _stackPanel = _jumpListControl.Descendants<VirtualizingStackPanel>()
                                     .Cast<VirtualizingStackPanel>()
                                     .SingleOrDefault();
        }

        return _stackPanel;
      }
    }

    /// <summary>
    /// Gets whether a VirtualizingStackPanel is being used to host our items
    /// </summary>
    private bool IsVirtualizing
    {
      get
      {
        return ItemsHostStackPanel != null;
      }
    }

    /// <summary>
    /// Gets the scrollviewer that hosts our jump list panel
    /// </summary>
    private ScrollViewer ScrollViewer
    {
      get
      {
        if (_stackPanel == null)
        {
          _scrollviewer = _jumpListControl.Descendants<ScrollViewer>()
                                      .SingleOrDefault() as ScrollViewer;
        }

        return _scrollviewer;
      }
    }

    /// <summary>
    /// Sets the vertical offset of the jump list
    /// </summary>
    private void SetVerticalOffset(double offset)
    {
      // implementation depends on whether a VSP is used
      // as the ItemsPanel
      if (IsVirtualizing)
      {
        ItemsHostStackPanel.SetVerticalOffset(offset);
      }
      else
      {
        ScrollViewer.ScrollToVerticalOffset(offset);
      }
    }

    /// <summary>
    /// Gets the vertical offset
    /// </summary>
    private double GetVerticalOffset()
    {
      // implementation depends on whether a VSP is used
      // as the ItemsPanel
      if (IsVirtualizing)
      {
        return ItemsHostStackPanel.ScrollOwner.VerticalOffset;
      }
      else
      {
        return ScrollViewer.VerticalOffset;
      }
    }

    /// <summary>
    /// Gets a list of categories
    /// </summary>
    public List<object> CategoryList
    {
      get
      {
        return _categoryList;
      }
      private set
      {
        _categoryList = value;
        OnPropertyChanged("CategoryList");
      }
    }

    #endregion

    #region public API

    /// <summary>
    /// Occurs when the selection changes.
    /// </summary>
    public event SelectionChangedEventHandler SelectionChanged;

    public JumpList()
    {
      DefaultStyleKey = typeof(JumpList);
      RebuildCategorisedList();

      // create a scroll animation
      _scrollAnimation = new DoubleAnimation();
      _scrollAnimation.EasingFunction = new SineEase();

      // create a storyboard for the animation
      _scrollStoryboard = new Storyboard();
      _scrollStoryboard.Children.Add(_scrollAnimation);
      Storyboard.SetTarget(_scrollAnimation, this);
      Storyboard.SetTargetProperty(_scrollAnimation, new PropertyPath("VerticalOffset"));

      // Make the Storyboard a resource.
      Resources.Add("anim", _scrollStoryboard);
    }

    public override void OnApplyTemplate()
    {
      base.OnApplyTemplate();

      _jumpListControl = this.GetTemplateChild("JumpListItems") as ItemsControl;
      _loadingIndicator = this.GetTemplateChild("LoadingIndicator") as FrameworkElement;
      _categoryItemsControl = this.GetTemplateChild("CategoryItems") as ItemsControl;
    }

    #endregion

    #region private methods

    private void ItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
      RebuildCategorisedList();
    }

    /// <summary>
    /// Handles LayoutUpdated event in order to hide the loading indicator
    /// </summary>
    private void CategoryItemsControl_LayoutUpdated(object sender, EventArgs e)
    {
      _categoryItemsControl.LayoutUpdated -= CategoryItemsControl_LayoutUpdated;

      _loadingIndicator.Visibility = System.Windows.Visibility.Collapsed;

      Dispatcher.BeginInvoke(() =>
      {
        ShowChildElements(_categoryItemsControl, TimeSpan.FromMilliseconds(CategoryTileAnimationDelay));
      });
    }

    /// <summary>
    /// Raises the SelectionChanged event
    /// </summary>
    protected void OnSelectionChanged(SelectionChangedEventArgs args)
    {
      if (SelectionChanged != null)
      {
        SelectionChanged(this, args);
      }
    }


    private void CategoryButton_Click(object sender, RoutedEventArgs e)
    {
      var categoryButton = sender as Button;

      // find the jump button for this category 
      var button = FlattenedCategories.OfType<Button>()
                                      .Where(b => b.Content.Equals(categoryButton.Content))
                                      .SingleOrDefault();

      // button is null if there are no items in the clicked category
      if (button != null)
      {
        // determine the location to scroll to
        double scrollToLocation = 0;
        if (IsVirtualizing)
        {
          // for virtualizing lists, this is simply the index
          scrollToLocation = FlattenedCategories.IndexOf(button);
        }
        else
        {
          // for non virtualizing lists, find the relative position of this item
          var container = button.Ancestors<StackPanel>().Single() as StackPanel;
          scrollToLocation = button.GetRelativePosition(container).Y;
        }

        if (ScrollDuration > 0.0)
        {
          _scrollAnimation.Duration = TimeSpan.FromMilliseconds(ScrollDuration);
          _scrollStoryboard.Duration = TimeSpan.FromMilliseconds(ScrollDuration);
          _scrollAnimation.To = scrollToLocation;
          _scrollAnimation.From = GetVerticalOffset();
          _scrollStoryboard.Begin();
        }
        else
        {
          SetVerticalOffset(scrollToLocation);
        }

        IsCategoryViewShown = false;
      }
    }

    /// <summary>
    /// Creates a categorised list of items, together with the category view items source
    /// </summary>
    private void RebuildCategorisedList()
    {
      if (ItemsSource == null)
        return;

      // adds each item into a category
      var categorisedItemsSource = ItemsSource.Cast<object>()
                                              .GroupBy(i => CategoryProvider.GetCategoryForItem(i))
                                              .OrderBy(g => g.Key)
                                              .ToList();
      
     
      // create the jump list
      var jumpListItems = new List<object>();
      foreach (var category in categorisedItemsSource)
      {
        jumpListItems.Add(new Button()
        {
          Content = category.Key,
          DataContext = category.Key,
          ContentTemplate = JumpButtonItemTemplate,
          Template = JumpButtonTemplate,
          Style = JumpButtonStyle
        });
        jumpListItems.AddRange(category.Select(item =>
         new JumpListItem()
         {
           Content = item,
           DataContext = item,
           Tag = item,
           ContentTemplate = ItemTemplate,
           Style = JumpListItemStyle
         }).Cast<object>());
      }

      // add interaction handlers
      foreach (var button in jumpListItems.OfType<Button>())
      {
        button.Click += JumpButton_Click;
      }
      foreach (var item in jumpListItems.OfType<JumpListItem>())
      {
        // handle events on the elements added to the ItemsControl
        item.MouseLeftButtonUp += JumpListItem_MouseLeftButtonUp;
        item.ManipulationStarted += JumpListItem_ManipulationStarted;
        item.ManipulationDelta += JumpListItem_ManipulationDelta;
      }

      FlattenedCategories = jumpListItems;

      // creates the category view, where the active state is determined by whether
      // there are any items in the category
      CategoryList = CategoryProvider.GetCategoryList(ItemsSource)
                                     .Select(category => new Button()
                                     {
                                       Content = category,
                                       IsEnabled = categorisedItemsSource.Any(categoryItems => categoryItems.Key.Equals(category)),
                                       ContentTemplate = this.CategoryButtonItemTemplate,
                                       Style = this.CategoryButtonStyle,
                                       Template = this.CategoryButtonTemplate
                                     }).Cast<object>().ToList();

      foreach (var button in CategoryList.OfType<Button>())
      {
        button.Click += CategoryButton_Click;
      }
    }

    private void JumpListItem_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
      _manipulationDeltaStarted = true;
    }

    private void JumpListItem_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
    {
      _manipulationDeltaStarted = false;
    }

    private void JumpListItem_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
      if (_manipulationDeltaStarted)
        return;

      var jumpListItem = sender as JumpListItem;
      var newSelectedItem = jumpListItem.Tag;
      SelectedItem = newSelectedItem;
    }

    private void JumpButton_Click(object sender, RoutedEventArgs e)
    {
      IsCategoryViewShown = true;
    }

    #endregion

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string property)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(property));
      }
    }

    #endregion

    /// <summary>
    /// Gets an ancestor with the given name
    /// </summary>
    private static T GetNamedAncestor<T>(FrameworkElement element, string name)
      where T : FrameworkElement
    {
      return element.AncestorsAndSelf<T>()
                   .Cast<T>()
                   .Where(a => a.Name == name)
                   .SingleOrDefault();
    }


    private static Storyboard GetStoryboardFromRootElement(FrameworkElement element, string storyboardName)
    {
      FrameworkElement rootElement = element.Elements().Cast<FrameworkElement>().First();
      return rootElement.Resources[storyboardName] as Storyboard;
    }

    private static void PrepareCategoryViewStoryboards(ItemsControl itemsControl, TimeSpan delayBetweenElement)
    {
      TimeSpan startTime = new TimeSpan(0);
      var elements = itemsControl.ItemsSource.Cast<FrameworkElement>().ToList();
      foreach (FrameworkElement element in elements)
      {
        var showStoryboard = GetStoryboardFromRootElement(element, "ShowAnim");
        if (showStoryboard != null)
        {
          showStoryboard.BeginTime = startTime;
        }

        var hideStoryboard = GetStoryboardFromRootElement(element, "HideAnim");
        if (hideStoryboard != null)
        {
          hideStoryboard.BeginTime = startTime;

          if (element == elements.Last())
          {
            hideStoryboard.Completed += (s, e) =>
            {
              itemsControl.Opacity = 0;
            };
          }
        }

        startTime = startTime.Add(delayBetweenElement);
      }
    }

    public static void ShowChildElements(ItemsControl itemsControl, TimeSpan delayBetweenElement)
    {
      itemsControl.Opacity = 1;
      PrepareCategoryViewStoryboards(itemsControl, delayBetweenElement);
      foreach (FrameworkElement element in itemsControl.ItemsSource)
      {
        var showStoryboard = GetStoryboardFromRootElement(element, "ShowAnim");
        if (showStoryboard != null)
        {
          showStoryboard.Begin();
        }
        else
        {
          element.Visibility = Visibility.Visible;
        }
      }
    }

    public static void HideChildElements(ItemsControl itemsControl, TimeSpan delayBetweenElement)
    {
      PrepareCategoryViewStoryboards(itemsControl, delayBetweenElement);
      foreach (FrameworkElement element in itemsControl.ItemsSource)
      {
        var hideStoryboard = GetStoryboardFromRootElement(element, "HideAnim");
        if (hideStoryboard != null)
        {
          hideStoryboard.Begin();
        }
        else
        {
          element.Visibility = Visibility.Collapsed;
        }
      }
    }

    #region value objects

    public class CategoryHeading
    {
      public object Category { get; set; }
      public bool IsActive { get; set; }
      public DataTemplate CategoryButtonItemTemplate { get; set; }
      public Style CategoryButtonStyle { get; set; }
      public ControlTemplate CategoryButtonTemplate { get; set; }
    }

    public class CategoryItems
    {
      public object Category { get; set; }
      public Style JumpButtonStyle { get; set; }
      public DataTemplate JumpButtonItemTemplate { get; set; }
      public ControlTemplate JumpButtonTemplate { get; set; }
      public DataTemplate ItemTemplate { get; set; }
      public List<object> Items { get; set; }
    }

    #endregion
  }



    public partial class JumpList
    {
        #region ItemsSource

        /// <summary>
        /// Gets or sets a collection used to generate the content of the JumpList. This is a Dependency Property.
        /// </summary>    

        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        /// <summary>
        /// Identifies the ItemsSource Dependency Property.
        /// <summary>
        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable),
            typeof(JumpList), new PropertyMetadata(null, OnItemsSourcePropertyChanged));


        private static void OnItemsSourcePropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnItemsSourcePropertyChanged(e);
        }

        partial void OnItemsSourcePropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region ItemTemplate

        /// <summary>
        /// Gets or sets the DataTemplate used to display each item. This is a Dependency Property.
        /// </summary>    

        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate)GetValue(ItemTemplateProperty); }
            set { SetValue(ItemTemplateProperty, value); }
        }

        /// <summary>
        /// Identifies the ItemTemplate Dependency Property.
        /// <summary>
        public static readonly DependencyProperty ItemTemplateProperty =
            DependencyProperty.Register("ItemTemplate", typeof(DataTemplate),
            typeof(JumpList), new PropertyMetadata(null, OnItemTemplatePropertyChanged));


        private static void OnItemTemplatePropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnItemTemplatePropertyChanged(e);
        }

        partial void OnItemTemplatePropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region JumpButtonItemTemplate

        /// <summary>
        /// Gets or sets the DataTemplate used to display the Jump buttons. The DataContext of each button is a group key. This is a Dependency Property.
        /// </summary>    

        public DataTemplate JumpButtonItemTemplate
        {
            get { return (DataTemplate)GetValue(JumpButtonItemTemplateProperty); }
            set { SetValue(JumpButtonItemTemplateProperty, value); }
        }

        /// <summary>
        /// Identifies the JumpButtonItemTemplate Dependency Property.
        /// <summary>
        public static readonly DependencyProperty JumpButtonItemTemplateProperty =
            DependencyProperty.Register("JumpButtonItemTemplate", typeof(DataTemplate),
            typeof(JumpList), new PropertyMetadata(null, OnJumpButtonItemTemplatePropertyChanged));


        private static void OnJumpButtonItemTemplatePropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnJumpButtonItemTemplatePropertyChanged(e);
        }

        partial void OnJumpButtonItemTemplatePropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region JumpButtonTemplate

        /// <summary>
        /// Gets or sets the ControlTemplate for the Jump buttons. This is a Dependency Property.
        /// </summary>    

        public ControlTemplate JumpButtonTemplate
        {
            get { return (ControlTemplate)GetValue(JumpButtonTemplateProperty); }
            set { SetValue(JumpButtonTemplateProperty, value); }
        }

        /// <summary>
        /// Identifies the JumpButtonTemplate Dependency Property.
        /// <summary>
        public static readonly DependencyProperty JumpButtonTemplateProperty =
            DependencyProperty.Register("JumpButtonTemplate", typeof(ControlTemplate),
            typeof(JumpList), new PropertyMetadata(null, OnJumpButtonTemplatePropertyChanged));


        private static void OnJumpButtonTemplatePropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnJumpButtonTemplatePropertyChanged(e);
        }

        partial void OnJumpButtonTemplatePropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region CategoryButtonItemTemplate

        /// <summary>
        /// Gets or sets the DataTemplate used to display the Category buttons. The DataContext of each Category button is an item from the ICategoryProvider.GetCategoryList list. This is a Dependency Property.
        /// </summary>    

        public DataTemplate CategoryButtonItemTemplate
        {
            get { return (DataTemplate)GetValue(CategoryButtonItemTemplateProperty); }
            set { SetValue(CategoryButtonItemTemplateProperty, value); }
        }

        /// <summary>
        /// Identifies the CategoryButtonItemTemplate Dependency Property.
        /// <summary>
        public static readonly DependencyProperty CategoryButtonItemTemplateProperty =
            DependencyProperty.Register("CategoryButtonItemTemplate", typeof(DataTemplate),
            typeof(JumpList), new PropertyMetadata(null, OnCategoryButtonItemTemplatePropertyChanged));


        private static void OnCategoryButtonItemTemplatePropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnCategoryButtonItemTemplatePropertyChanged(e);
        }

        partial void OnCategoryButtonItemTemplatePropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region CategoryButtonTemplate

        /// <summary>
        /// Gets or sets the ControlTemplate for the Category buttons. This is a Dependency Property.
        /// </summary>    

        public ControlTemplate CategoryButtonTemplate
        {
            get { return (ControlTemplate)GetValue(CategoryButtonTemplateProperty); }
            set { SetValue(CategoryButtonTemplateProperty, value); }
        }

        /// <summary>
        /// Identifies the CategoryButtonTemplate Dependency Property.
        /// <summary>
        public static readonly DependencyProperty CategoryButtonTemplateProperty =
            DependencyProperty.Register("CategoryButtonTemplate", typeof(ControlTemplate),
            typeof(JumpList), new PropertyMetadata(null, OnCategoryButtonTemplatePropertyChanged));


        private static void OnCategoryButtonTemplatePropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnCategoryButtonTemplatePropertyChanged(e);
        }

        partial void OnCategoryButtonTemplatePropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region CategoryProvider

        /// <summary>
        /// Gets or sets a category provider which groups the items in the JumpList and specifies the categories in the jump menu. This is a Dependency Property.
        /// </summary>    

        public ICategoryProvider CategoryProvider
        {
            get { return (ICategoryProvider)GetValue(CategoryProviderProperty); }
            set { SetValue(CategoryProviderProperty, value); }
        }

        /// <summary>
        /// Identifies the CategoryProvider Dependency Property.
        /// <summary>
        public static readonly DependencyProperty CategoryProviderProperty =
            DependencyProperty.Register("CategoryProvider", typeof(ICategoryProvider),
            typeof(JumpList), new PropertyMetadata(null, OnCategoryProviderPropertyChanged));


        private static void OnCategoryProviderPropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnCategoryProviderPropertyChanged(e);
        }

        partial void OnCategoryProviderPropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region JumpButtonStyle

        /// <summary>
        /// Gets or sets the style applied to the Jump buttons. This should be a style with a TargetType of Button. This is a Dependency Property.
        /// </summary>    

        public Style JumpButtonStyle
        {
            get { return (Style)GetValue(JumpButtonStyleProperty); }
            set { SetValue(JumpButtonStyleProperty, value); }
        }

        /// <summary>
        /// Identifies the JumpButtonStyle Dependency Property.
        /// <summary>
        public static readonly DependencyProperty JumpButtonStyleProperty =
            DependencyProperty.Register("JumpButtonStyle", typeof(Style),
            typeof(JumpList), new PropertyMetadata(null, OnJumpButtonStylePropertyChanged));


        private static void OnJumpButtonStylePropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnJumpButtonStylePropertyChanged(e);
        }

        partial void OnJumpButtonStylePropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region CategoryButtonStyle

        /// <summary>
        /// Gets or sets the style applied to the Category buttons. This should be a style with a TargetType of Button. This is a Dependency Property.
        /// </summary>    

        public Style CategoryButtonStyle
        {
            get { return (Style)GetValue(CategoryButtonStyleProperty); }
            set { SetValue(CategoryButtonStyleProperty, value); }
        }

        /// <summary>
        /// Identifies the CategoryButtonStyle Dependency Property.
        /// <summary>
        public static readonly DependencyProperty CategoryButtonStyleProperty =
            DependencyProperty.Register("CategoryButtonStyle", typeof(Style),
            typeof(JumpList), new PropertyMetadata(null, OnCategoryButtonStylePropertyChanged));


        private static void OnCategoryButtonStylePropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnCategoryButtonStylePropertyChanged(e);
        }

        partial void OnCategoryButtonStylePropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region CategoryTileAnimationDelay

        /// <summary>
        /// Gets or sets the time delay in milliseconds between firing the animations which reveal the Category button. This is a Dependency Property.
        /// </summary>    

        public double CategoryTileAnimationDelay
        {
            get { return (double)GetValue(CategoryTileAnimationDelayProperty); }
            set { SetValue(CategoryTileAnimationDelayProperty, value); }
        }

        /// <summary>
        /// Identifies the CategoryTileAnimationDelay Dependency Property.
        /// <summary>
        public static readonly DependencyProperty CategoryTileAnimationDelayProperty =
            DependencyProperty.Register("CategoryTileAnimationDelay", typeof(double),
            typeof(JumpList), new PropertyMetadata(20.0, OnCategoryTileAnimationDelayPropertyChanged));


        private static void OnCategoryTileAnimationDelayPropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnCategoryTileAnimationDelayPropertyChanged(e);
        }

        partial void OnCategoryTileAnimationDelayPropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region ScrollDuration

        /// <summary>
        /// Gets or sets the time taken to 'jump' to a new list location in milliseconds. This is a Dependency Property.
        /// </summary>    

        public double ScrollDuration
        {
            get { return (double)GetValue(ScrollDurationProperty); }
            set { SetValue(ScrollDurationProperty, value); }
        }

        /// <summary>
        /// Identifies the ScrollDuration Dependency Property.
        /// <summary>
        public static readonly DependencyProperty ScrollDurationProperty =
            DependencyProperty.Register("ScrollDuration", typeof(double),
            typeof(JumpList), new PropertyMetadata(200.0, OnScrollDurationPropertyChanged));


        private static void OnScrollDurationPropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnScrollDurationPropertyChanged(e);
        }

        partial void OnScrollDurationPropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region SelectedItem

        /// <summary>
        /// Gets or sets the selected item. This is a Dependency Property.
        /// </summary>    

        public object SelectedItem
        {
            get { return (object)GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        /// <summary>
        /// Identifies the SelectedItem Dependency Property.
        /// <summary>
        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem", typeof(object),
            typeof(JumpList), new PropertyMetadata(null, OnSelectedItemPropertyChanged));


        private static void OnSelectedItemPropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnSelectedItemPropertyChanged(e);
        }

        partial void OnSelectedItemPropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region IsCategoryViewShown

        /// <summary>
        /// Gets or sets whether the category view is currently shown. This is a Dependency Property.
        /// </summary>    

        public bool IsCategoryViewShown
        {
            get { return (bool)GetValue(IsCategoryViewShownProperty); }
            set { SetValue(IsCategoryViewShownProperty, value); }
        }

        /// <summary>
        /// Identifies the IsCategoryViewShown Dependency Property.
        /// <summary>
        public static readonly DependencyProperty IsCategoryViewShownProperty =
            DependencyProperty.Register("IsCategoryViewShown", typeof(bool),
            typeof(JumpList), new PropertyMetadata(false, OnIsCategoryViewShownPropertyChanged));


        private static void OnIsCategoryViewShownPropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnIsCategoryViewShownPropertyChanged(e);
        }

        partial void OnIsCategoryViewShownPropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion

        #region JumpListItemStyle

        /// <summary>
        /// Gets or sets the style applied to each jump list item. This is a Dependency Property.
        /// </summary>    

        public Style JumpListItemStyle
        {
            get { return (Style)GetValue(JumpListItemStyleProperty); }
            set { SetValue(JumpListItemStyleProperty, value); }
        }

        /// <summary>
        /// Identifies the JumpListItemStyle Dependency Property.
        /// <summary>
        public static readonly DependencyProperty JumpListItemStyleProperty =
            DependencyProperty.Register("JumpListItemStyle", typeof(Style),
            typeof(JumpList), new PropertyMetadata(null, OnJumpListItemStylePropertyChanged));


        private static void OnJumpListItemStylePropertyChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            JumpList myClass = d as JumpList;

            myClass.OnJumpListItemStylePropertyChanged(e);
        }

        partial void OnJumpListItemStylePropertyChanged(DependencyPropertyChangedEventArgs e);


        #endregion
    }
}
